"""分类模型的评估和回归模型的评估侧重点不一样，
回归模型一般针对连续型的数据，而分类模型一般针对的是离散的数据。

所以，评估分类模型时，评估指标与回归模型也很不一样，
比如，分类模型的评估指标通常包括准确率、精确率、召回率和F1分数等等。
而回归模型的评估指标通常包括均方误差（MSE）、均方根误差（RMSE）和平均绝对误差（MAE）等等，
不过，这些指标衡量的都是预测值与真实值之间的数值差异。

关于回归模型的评估，可以参考之前的文章，本篇开始，主要讨论分类模型的评估。

1. 准确率分数
准确率分数（accuracy score）代表了模型正确分类的样本比例，它能够直观地反映出模型在分类任务上的准确度。
不过，在处理不平衡数据集时，需要注意的是，准确率分数并不能完全反映模型的性能。

1.1. 计算公式
accuracy(y,^y)=1n∑n−1i=01(^yi=yi)其中，n是样本数量，yi是真实值，^yi是预测值。

1.2. 使用示例"""
from sklearn.metrics import accuracy_score
from sklearn.metrics import top_k_accuracy_score
from sklearn.metrics import balanced_accuracy_score
from sklearn.metrics import precision_score, recall_score, f1_score
import numpy as np
n = 100
y_true = np.random.randint(1, 10, n)
y_pred = np.random.randint(1, 10, n)

s1 = accuracy_score(y_true, y_pred)
s2 = accuracy_score(y_true, y_pred, normalize=False)
print("准确率比例：{}，准确率计数：{}".format(s1, s2))

"""# 运行结果
准确率比例：0.16，准确率计数：16
上例中，预测值和真实值是随机生成的，所以你的运行结果不一定和我这个一样。
accuracy_score默认是计算正确的比率，如果加上参数normalize=False，则计算正确的数量。

2. top-k 准确率分数
top-k 准确率分数（top-k accuracy score）用于衡量模型在前 k 个预测结果中的正确率。
不同的k值会得到不同的top-k准确率，这可以帮助我们更全面地了解模型的性能。

2.1. 计算公式
top-k accuracy(y,^f)=1n∑n−1i=0∑kj=11(^fi,j=yi)其中，n是样本数量，yi是真实值，^fi,j是对应于第j最大预测分数的第i样本的预测类别。
k是允许的猜测次数，1(x)
是指示函数。
关于指示函数是什么，可以参考：https://en.wikipedia.org/wiki/Indicator_function

2.2. 使用示例"""

n = 100
y_true = np.random.randint(1, 10, n)
y_score = np.random.rand(n, 9)

s1 = top_k_accuracy_score(y_true, y_score, k=2)
s2 = top_k_accuracy_score(y_true, y_score, k=2, normalize=False)
print("top-k 准确率比例：{}，top-k 准确率计数：{}".format(s1, s2))

"""# 运行结果
top-k 准确率比例：0.23，top-k 准确率计数：23
top-k 准确率分数计算时，不是用真实值和预测值，用的是真实值和top-k中预测值的正确率。

3. 平衡准确率分数
平衡准确率分数（balanced accuracy score）特别适用于针对不平衡数据集时的性能评估，
它可以避免某一类样本的预测性能被过度夸大，从而能够更准确地评估模型的性能。

不过，平衡准确率适用于二元分类问题，对于多类分类问题可能需要使用其他扩展的平衡性能指标进行评估。

3.1. 计算公式
balanced-accuracy(y,^y,w)=1∑^wi∑i1(^yi=yi)^wi其中，n是样本数量，yi是真实值，^yi是预测值。
而 ^wi=wi∑j1(yj=yi)wj，1(x)是指示函数， wi是对应的样本权重。

3.2. 使用示例"""

n = 100
y_true = np.random.randint(1, 10, n)
y_pred = np.random.randint(1, 10, n)

s = balanced_accuracy_score(y_true, y_pred)
print("平均准确率：{}".format(s))
"""
# 运行结果
平均准确率：0.17929799866074375
4. 精确率、召回率和 F1 度量
介绍精确率、召回率和 F1 度量之前，先介绍几个概念。


                实际结果（真）         	        实际结果（假）
预测结果（真）	tp（true positive）真阳性	    fp（false positive）假阳性
预测结果（假）	fn（false negative）假阴性	tn（true negative）真阴性
其中，tp和tn是预测结果与实际结果相符；fp和fn是预测结果与实际结果不符。

4.1. 计算公式
基于上面的概念，下面定义精确率、召回率和 F1 度量了。

精确率：
precision=tp/tp+fp
它用于衡量模型的查准性能，即模型预测为真的样本中有多少是真正的真。

召回率：
recall=tp/tp+fn

它用于衡量模型的查全性能，即模型能够找出多少真正的真。

F1度量：
F1=2×precision×recall/precision+recall
它是精确率和召回率的调和平均数，用于综合评价模型的性能。

4.2. 使用示例"""

n = 100
y_true = np.random.randint(0, 2, n)
y_pred = np.random.randint(0, 2, n)

p = precision_score(y_true, y_pred)
r = recall_score(y_true, y_pred)
f1 = f1_score(y_true, y_pred)
print("精确率：{}\n召回率：{}\nF1度量：{}".format(p, r, f1))

# 运行结果
"""精确率：0.4489795918367347
召回率：0.4782608695652174
F1度量：0.46315789473684216
5. 总结
本篇归纳总结了分类模型中关于准确率相关的一些评估方法：

准确率分数
top-k 准确率分数
平衡准确率分数
精确率，召回率和 F1度量"""